﻿using CinemaMaestro.DataLayer.Contracts;
using CinemaMaestro.DataLayer.Contracts.Entities;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;

namespace CinemaMaestro.DataLayer.Entity
{
    public class MovieRepository : IRepository<Movie>
    {
        private DbSet<Movie> _dbSet;
        private DbContext _ctx;

        public MovieRepository(DbContext context)
        {
            _dbSet = context.Set<Movie>();
            _ctx = context;
        }

        public IQueryable<Movie> Read()
        {
            return _dbSet;
        }

        public Movie Create(Movie entity)
        {
            var actors = entity.Actors;
            entity.Actors = new List<Actor>();
            foreach (var actor in actors)
            {
                _ctx.Set<Actor>().Attach(actor);
                entity.Actors.Add(actor);
            }
            var directors = entity.Directors;
            entity.Directors = new List<Director>();
            foreach (var director in directors)
            {
                _ctx.Set<Director>().Attach(director);
                entity.Directors.Add(director);
            }
            var categories = entity.Categories;
            entity.Categories = new List<Category>();
            foreach (var category in categories)
            {
                _ctx.Set<Category>().Attach(category);
                entity.Categories.Add(category);
            }
            var created = _dbSet.Add(entity);            
            return created;
        }

        public void Update(Movie entity)
        {
            var existingMovie = _dbSet.First(x => x.Id == entity.Id);
            var existingActors = existingMovie.Actors.ToList();
            foreach (var actor in existingActors)
            {
                existingMovie.Actors.Remove(actor);
            }
            
            foreach (var actor in entity.Actors)
            {
                var attachedActor = _ctx.Set<Actor>().First(x => x.Id == actor.Id);
                existingMovie.Actors.Add(attachedActor);
            }

            var existingDirectors = existingMovie.Directors.ToList();
            foreach (var director in existingDirectors)
            {
                existingMovie.Directors.Remove(director);
            }

            foreach (var director in entity.Directors)
            {
                var attachedDirector = _ctx.Set<Director>().First(x => x.Id == director.Id);
                existingMovie.Directors.Add(attachedDirector);
            }

            var existingCategories = existingMovie.Categories.ToList();
            foreach (var category in existingCategories)
            {
                existingMovie.Categories.Remove(category);
            }

            foreach (var category in entity.Categories)
            {
                var attachedCategory = _ctx.Set<Category>().First(x => x.Id == category.Id);
                existingMovie.Categories.Add(attachedCategory);
            }

            existingMovie.Title = entity.Title;
            existingMovie.Image = entity.Image;
            existingMovie.ReleaseDate = entity.ReleaseDate;
            existingMovie.Duration = entity.Duration;
            existingMovie.Description = entity.Description;
            
        }

        public bool Delete(int id)
        {
            var instance = _dbSet.
                FirstOrDefault(x => x.Id == id);

            if (instance != null)
            {
                var actors = instance.Actors.ToList();
                foreach (var actor in actors) {
                    instance.Actors.Remove(actor);
                }
                var directors = instance.Directors.ToList();
                foreach (var director in directors)
                {
                    instance.Directors.Remove(director);
                }
                var categories = instance.Categories.ToList();
                foreach (var category in categories)
                {
                    instance.Categories.Remove(category);
                }

                _dbSet.Remove(instance);
                return true;
            }
            else
            {
                return false;
            }
        }

    }
}
